#include <gtest/gtest.h>
#include <gmock/gmock.h>
#include <type_system/schema.hpp>
#include <type_system/schema_parser.hpp>
#include <processing/introspection_query_handler.hpp>
#include <processing/parse_document.hpp>
#include <processing/serialize_result.hpp>
#include <processing/processing_pipeline.hpp>
#include <processing/process_errors.hpp>
#include <data/sql/postgresql_renderer.hpp>
#include <data/sql/postgresql_data_reader.hpp>
#include <serialization/json/json_serializer.hpp>
#include <serialization/buffer_writer.hpp>
#include <struct/query_context.hpp>
#include <type_system/builtin_types.hpp>

#include <string>

using namespace blitz_query_cpp;

TEST(Introspection, SimpleSelect)
{
    std::string scm = R""""(
        schema { query: Query }
        type Query
        {
           Users :[User]
        }
        type User @table(table: "user" schema: "test")
        {
           Id: Int @column(name: "id" IsPK: True)
           Name: String @column(name: "name")
           Age: Int  @column(name: "age")
           AccountId :Int @always_projected
        }

        directive @table(table: String schema: String) on OBJECT
        directive @column(name: String IsPK: Boolean = False) on FIELD_DEFINITION
        )"""";

    std::string query =
        R""""(
{
  __type(name: "Query") {
    name
    description
    kind
    fields {
      name
      isDeprecated
      args {
        name
        type {
          name
        }
      }
      description
      type {
        kind
        name
        ofType
        {
          name
          kind
          ofType
          {
            name
          }
        }
      }
    }
  }
}
        )"""";

    schema_t my_schema;
    EXPECT_EQ(add_introspection_types(my_schema), true);

    schema_parser_t parser;
    bool res = parser.parse(my_schema, scm);
    EXPECT_EQ(res, true);
    EXPECT_EQ(my_schema.query_type_name, "Query");
    EXPECT_EQ(parser.get_error_msg().size(), 0ul);
  
    std::cout << parser.get_error_msg() << std::endl;
    
    options_t options{};

    query_context context(query, &my_schema, options);

    processing_pipeline<parse_document,
                        introspection_query_handler,
                        process_errors,
                        serialize_result<json_writer<buffer_writer>>
                       >
        pipeline;

    pipeline.process(context);
    EXPECT_EQ(context.error_msgs.size(), 0ul);
    std::string &result = context.data["result_str"];
    EXPECT_GT(result.size(), 0ul);

    std::cout << result << std::endl;
}